package com.aptemo.webetek.server;

import java.util.ArrayList;
import java.util.List;
import java.util.logging.Logger;

import javax.jdo.PersistenceManager;
import javax.jdo.Query;
import javax.servlet.ServletException;

import com.aptemo.webetek.client.WebetekUserService;
import com.aptemo.webetek.client.commands.Action;
import com.aptemo.webetek.client.commands.Response;
import com.aptemo.webetek.client.commands.impl.GetStatisticsAction.EStatsPeriod;
import com.aptemo.webetek.client.enums.EnumEventStatus;
import com.aptemo.webetek.client.exceptions.BackendException;
import com.aptemo.webetek.client.exceptions.WebetekLoginException;
import com.aptemo.webetek.client.exceptions.BackendException.EErrorCodes;
import com.aptemo.webetek.server.data.Bet;
import com.aptemo.webetek.server.data.BetLabel;
import com.aptemo.webetek.server.data.PMF;
import com.aptemo.webetek.server.data.Pick;
import com.aptemo.webetek.server.data.Stake;
import com.aptemo.webetek.server.data.UserGroup;
import com.aptemo.webetek.server.data.WebetekUser;
import com.aptemo.webetek.server.datastore.DataStoreAPI;
import com.aptemo.webetek.shared.LabelBean;
import com.aptemo.webetek.shared.LoginBean;
import com.aptemo.webetek.shared.PickBean;
import com.aptemo.webetek.shared.StatisticsBean;
import com.google.appengine.api.datastore.Key;
import com.google.appengine.api.datastore.KeyFactory;
import com.google.appengine.api.users.User;
import com.google.appengine.api.users.UserService;
import com.google.appengine.api.users.UserServiceFactory;
import com.google.gwt.user.server.rpc.RemoteServiceServlet;

/**
 * The server side implementation of the RPC service.
 */
@SuppressWarnings("serial")
public class WebetekUserServiceImpl
		extends RemoteServiceServlet implements WebetekUserService
{

	private CommonService		utils		= new CommonService();
	private UserService			userService	= UserServiceFactory.getUserService();

	private static final Logger	log			= Logger.getLogger(WebetekUserServiceImpl.class.getName());

	private DataStoreAPI		dbAPI;

	private ActionInvoker		invoker		= new ActionInvoker();

	@Override
	public <T extends Response> T invoke(Action<T> action) throws BackendException, WebetekLoginException
	{

		try
		{
			return (T) invoker.invoke(action, getThreadLocalRequest());
		}
		catch (BackendException e)
		{
			log.info(e.getLocalizedMessage());
			throw e;
		}
		catch (WebetekLoginException e)
		{
			log.info(e.getLocalizedMessage());
			throw e;
		}
		catch (NullPointerException e)
		{

			if (action != null)
			{
				log.severe("Null pointer exception when executing: " + action.getClass().getName());
				throw new BackendException(EErrorCodes.SERVER_ERROR);
			}
			throw new BackendException(EErrorCodes.SERVER_ERROR);
		}
		catch (Exception e)
		{
			e.printStackTrace();
			log.severe(e.getLocalizedMessage());

			// throw new BackendException(EErrorCodes.SERVER_ERROR,
			// e.getLocalizedMessage());
			throw new BackendException(EErrorCodes.SERVER_ERROR);
		}
	}

	//
	// public String getServletUrl()
	// {
	// HttpServletRequest req = super.getThreadLocalRequest();
	//
	// // TODO in case of unit test
	// if (req == null)
	// {
	// return "";
	// }
	//
	// String scheme = req.getScheme(); // http
	// String serverName = req.getServerName(); // hostname.com
	// int serverPort = req.getServerPort(); // 80
	// String contextPath = req.getContextPath(); // /mywebapp
	//
	// String url = scheme + "://" + serverName + ":" + serverPort +
	// contextPath;
	// return url;
	// }

	//
	// private void checkLogin() throws WebetekLoginException
	// {
	// if (!userService.isUserLoggedIn())
	// {
	// throw new WebetekLoginException("Not logged in",
	// userService.createLoginURL(""));
	// }
	// }
	//
	// private boolean isTeamMember(PersistenceManager pm, UserGroup group)
	// {
	// User user = userService.getCurrentUser();
	// if (user != null)
	// {
	// return isTeamMember(pm, group, user.getEmail());
	// }
	// return false;
	// }
	//
	// private boolean isTeamMember(PersistenceManager pm, UserGroup team,
	// String email)
	// {
	// return isTeamMember(pm, team, email, EnumUserStatus.ACTIVE);
	// // List<WebetekUser> users = utils.getUser(pm, email);
	// // for (WebetekUser user : users)
	// // {
	// // if (user.getParent().equals(team) && user.getStatus() ==
	// // EnumUserStatus.ACTIVE)
	// // return true;
	// // }
	// // return false;
	// }

	// private boolean isTeamMember(PersistenceManager pm, UserGroup team,
	// String email, EnumUserStatus status)
	// {
	// for (WebetekUser user : team.getPlayers())
	// {
	// if ((status == null || user.getStatus() == status) &&
	// (email.equals(user.getEmail())))
	// {
	// return true;
	// }
	// }
	// // List<WebetekUser> users = utils.getUser(pm, email);
	// // for (WebetekUser user : users)
	// // {
	// // if (user.getParent().equals(team) && (status == null ||
	// // user.getStatus() == status))
	// // {
	// // return true;
	// // }
	// // }
	// return false;
	// }

	// private boolean isTeamEditor(PersistenceManager pm, UserGroup team)
	// throws BackendException
	// {
	// WebetekUser user = utils.getUser(pm, userService, team);
	// if (userService.isUserAdmin())
	// {
	// return true;
	// }
	// if (user == null || user.getRole() != EnumRole.EDITOR)
	// {
	// throw new BackendException(EErrorCodes.NOT_TEAM_EDITOR);
	// }
	// return true;
	// }
	//
	// private boolean isWebetekUser(PersistenceManager pm) throws
	// WebetekLoginException
	// {
	// List<WebetekUser> list = utils.getUser(pm, userService);
	// return list.size() > 0 ? true : false;
	// }
	//
	// private boolean isWebetekUser(PersistenceManager pm, String email) throws
	// WebetekLoginException
	// {
	// List<WebetekUser> list = utils.getUser(pm, email);
	// return list.size() > 0 ? true : false;
	// }

	// private boolean isTeamOwner(PersistenceManager pm, WebetekUser user)
	// {
	// UserGroup team = user.getParent(pm);
	//
	// if (team.getOwnerKey().equals(user.getKey()))
	// {
	// return true;
	// }
	// return false;
	// }

	// private boolean isTeamOwner(PersistenceManager pm, String teamId)
	// {
	// Key key = KeyFactory.stringToKey(teamId);
	// UserGroup team = pm.getObjectById(UserGroup.class, teamId);
	//
	// WebetekUser user = utils.getUser(pm, userService, team);
	//
	// if (team.getOwnerKey().equals(user.getKey()))
	// {
	// return true;
	// }
	// return false;
	// }

	private UserGroup extractTeam(String teamId, PersistenceManager pm) throws BackendException
	{
		if (null == teamId || teamId.isEmpty())
		{
			throw new BackendException(EErrorCodes.INVALID_ID);
		}

		Key key = KeyFactory.stringToKey(teamId);
		if (null == key)
		{
			throw new BackendException(EErrorCodes.INVALID_ID);
		}

		UserGroup team = pm.getObjectById(UserGroup.class, key);
		return team;
	}

	private UserGroup getAdminGroup()
	{
		PersistenceManager pm = PMF.get().getPersistenceManager();
		try
		{
			UserGroup group = null;

			Query query = pm.newQuery(UserGroup.class);
			query.setFilter("name == 'AdminGroup'");
			List<UserGroup> users = (List<UserGroup>) query.execute();
			if (users.size() == 0)
			{
				// creating a new one!

				// createUserGroup("AdminGroup", "Predefined Admin group",
				// true);

				group = new UserGroup("AdminGroup");
				group.setPublic(true);
				group.setDescription("Predefined Admin group");

				pm.makePersistent(group);
			}
			else
			{
				group = users.get(0);
			}
			return group;
		}
		finally
		{
			pm.close();
		}
	}

	// private long getBetTreshold()
	// {
	// return TIME_FUSE_CONST;
	// }

	//
	// public UserBean getPlayerDetails(String userid) throws
	// WebetekLoginException, BackendException
	// {
	// return getPlayerDetails(userid, "");
	// }
	//
	// public UserBean getPlayerDetails(String userid, String teamId) throws
	// WebetekLoginException, BackendException
	// {
	// checkLogin();
	//
	// UserBean bean;
	// if (userid != null && !userid.isEmpty())
	// {
	// bean = dbAPI.getPlayer(userid);
	// }
	// else
	// {
	// if ((teamId == null) || teamId.isEmpty())
	// {
	// throw new BackendException(EErrorCodes.INVALID_ID);
	// }
	// PersistenceManager pm = PMF.get().getPersistenceManager();
	// try
	// {
	//
	// WebetekUser user;
	// UserGroup team = extractTeam(teamId, pm);
	// user = utils.getUser(pm, userService, team);
	//
	// bean = user.toBean();
	// }
	// finally
	// {
	// pm.close();
	// }
	// }
	// // set user admin mode...
	// if (userService.isUserAdmin())
	// {
	// bean.setRole(EnumRole.ADMIN);
	// }
	// return bean;
	//
	// // PersistenceManager pm = PMF.get().getPersistenceManager();
	// // try
	// // {
	// // WebetekUser user;
	// // if (userid == null || userid.isEmpty())
	// // {
	// // if ((teamId == null) || teamId.isEmpty())
	// // {
	// // throw new BackendException(EErrorCodes.INVALID_ID);
	// // }
	// //
	// // UserGroup team = extractTeam(teamId, pm);
	// // user = utils.getUser(pm, userService, team);
	// // }
	// // else
	// // {
	// //
	// // Key key = KeyFactory.stringToKey(userid);
	// // user = pm.getObjectById(WebetekUser.class, key);
	// // }
	// // if (user == null)
	// // {
	// // throw new BackendException(EErrorCodes.NOT_WEBETEK_USER);
	// // }
	// //
	// // UserBean bean = user.toBean();
	// // // set user admin mode...
	// // if (userService.isUserAdmin())
	// // {
	// // bean.setRole(EnumRole.ADMIN);
	// // }
	// // return bean;
	// // }
	// // finally
	// // {
	// // pm.close();
	// // }
	//
	// }

	public LoginBean getCurrentUserLoginInfo(String path) throws BackendException
	{
		PersistenceManager pm = PMF.get().getPersistenceManager();

		try
		{
			LoginBean login = null;
			User currentUser = userService.getCurrentUser();
			if (null == currentUser)
			{
				login = new LoginBean("");
			}
			else
			{
				String email = currentUser.getEmail();
				login = new LoginBean(email);
				if ((userService.isUserAdmin()))
				{
					login.setAdmin(true);
					// UserGroupBean usergroup = createUserGroup("AdminGroup",
					// "Predefined Admin group", false);
					List<WebetekUser> wuser = utils.getUser(pm, email);
					if (wuser.size() == 0)
					{
						// create user admin if none
						// createAdminUser(email);
					}
				}
				else
				{
				}

				// TODO set favourites
				// get login info...
				// login.setFavourites();

			}

			login.setLoggedIn(userService.isUserLoggedIn());
			login.setLoginUrl(userService.createLoginURL(path));
			login.setLogoutUrl(userService.createLogoutURL(path));

			return login;
		}
		finally
		{
			pm.close();
		}

	}

	//
	// public ArrayList<GameBean> getBets(String teamId, String labelId, Date
	// treshold, EnumGameStatus enumBetStatus) throws WebetekLoginException,
	// BackendException
	// {
	// // checkLogin();
	//
	// return dbAPI.getGames(teamId, labelId, treshold, enumBetStatus);
	//
	// }
	//
	// private Pick checkStakeMatch(PersistenceManager pm, WebetekUser user, Bet
	// bet)
	// {
	// List<Stake> stakes = user.getStakes();
	// for (Stake item : stakes)
	// {
	// List<Key> pickkeys = item.getPickKeys();
	// for (Key pickkey : pickkeys)
	// {
	// Pick pick = pm.getObjectById(Pick.class, pickkey);
	// Bet tbet = pick.getParent(pm);
	//
	// if (tbet.equals(bet))
	// {
	// return pick;
	// }
	//
	// }
	//
	// }
	// return null;
	// }
	//
	// public GameBean createGame(Date date, String teamid, String title, String
	// description, ArrayList<PickBean> picks, EnumBetType betType)
	// throws BackendException, WebetekLoginException
	// {
	// return createGame(date, teamid, title, description, picks, betType,
	// null);
	// }
	//
	// public GameBean createGame(Date date, String teamid, String title, String
	// description, ArrayList<PickBean> picks, EnumBetType betType, String
	// labelId)
	// throws BackendException, WebetekLoginException
	// {
	// checkLogin();
	//
	// PersistenceManager pm = PMF.get().getPersistenceManager();
	// try
	// {
	// // check date
	// if (date.before(new Date(System.currentTimeMillis() + getBetTreshold())))
	// {
	// throw new BackendException(EErrorCodes.BET_DATE_EXCEEDED);
	// }
	//
	// // check if number of picks corresponds bet type
	// if (betType.getValue() != picks.size())
	// {
	// throw new BackendException(EErrorCodes.INVALID_NO_OF_PICKS);
	// }
	//
	// Bet bet = new Bet(date, title, description, betType);
	// //
	// UserGroup team = extractTeam(teamid, pm);
	// team.addBet(bet);
	//
	// // add picks...
	// // ArrayList<Pick> picks = new ArrayList<Pick>();
	// for (PickBean item : picks)
	// {
	// Pick pick = new Pick(item.getTitle());
	// // picks.add(pick);
	// bet.addPick(pick);
	// }
	// // bet.setPicks(picks);
	//
	// try
	// {
	// if (labelId != null && !labelId.isEmpty())
	// {
	// BetLabel label = pm.getObjectById(BetLabel.class, labelId);//
	// team.findLabel(labelTitle);
	// if (label != null)
	// {
	// bet.addLabel(label.getKey());
	// }
	// }
	// }
	// catch (JDOObjectNotFoundException e)
	// {
	// e.printStackTrace();
	// }
	//
	// return bet.toBean();
	// }
	// finally
	// {
	// pm.close();
	// }
	//
	// }
	//
	// public GameBean modifyGame(GameBean ibet) throws WebetekLoginException,
	// BackendException
	// {
	// checkLogin();
	// // check membership
	// isBetEditor(ibet.getKey());
	//
	// return dbAPI.modifyGame(ibet);
	//
	// // String id = ibet.getKey();
	// // Date date = ibet.getDate();
	// // String title = ibet.getTitle();
	// // String description = ibet.getDescription();
	// // ArrayList<PickBean> pickbeans = ibet.getPicks();
	// // ArrayList<String> labels = ibet.getLabels();
	// //
	// // PersistenceManager pm = PMF.get().getPersistenceManager();
	// //
	// // // Transaction tx = pm.currentTransaction();
	// //
	// // try
	// // {
	// // // tx.begin();
	// //
	// // Key key = KeyFactory.stringToKey(id);
	// // Bet bet = pm.getObjectById(Bet.class, key);
	// //
	// // // check membership
	// // if (!isTeamEditor(pm, bet.getParent()))
	// // {
	// // throw new BackendException(EErrorCodes.NOT_TEAM_EDITOR);
	// // }
	// //
	// // // update object...
	// // bet.setDate(date);
	// // bet.setDescription(description);
	// // bet.setTitle(title);
	// //
	// // for (Pick pick : bet.getPicks())
	// // {
	// // PickBean pb = null;
	// // for (PickBean item : pickbeans)
	// // {
	// // if (item.getId().equals(pick.getSid()))
	// // {
	// // pb = item;
	// // break;
	// // }
	// // }
	// // if (pb != null)
	// // {
	// // pick.setTitle(pb.getTitle());
	// // }
	// //
	// // }
	// //
	// // if (labels != null)
	// // {
	// // List<Key> betlabels = new ArrayList<Key>();
	// // for (String labelkey : labels)
	// // {
	// // Key lkey = KeyFactory.stringToKey(labelkey);
	// //
	// // betlabels.add(lkey);
	// // }
	// // bet.setLabels(betlabels);
	// // }
	// //
	// // Date currentTime = new Date(System.currentTimeMillis());
	// // // check new bet date...
	// // if (bet.getDate().before(currentTime))
	// // {
	// // // check if result assigned..
	// // if (bet.getStatus() == EnumBetStatus.ACTIVE)
	// // {
	// // bet.setStatus(EnumBetStatus.WAITINGRESULTS);
	// // }
	// // }
	// // else if (bet.getDate().after(currentTime))
	// // {
	// // if (bet.getStatus() == EnumBetStatus.WAITINGRESULTS)
	// // {
	// // bet.setStatus(EnumBetStatus.ACTIVE);
	// // }
	// //
	// // }
	// //
	// // return bet.toBean();
	// // }
	// // finally
	// // {
	// // pm.close();
	// // }
	// }
	//
	// public ResponseStatus deleteGame(String id) throws WebetekLoginException,
	// BackendException
	// {
	// checkLogin();
	//
	// // check membership
	// isBetEditor(id);
	//
	// return dbAPI.deleteGame(id);
	// // PersistenceManager pm = PMF.get().getPersistenceManager();
	// // try
	// // {
	// // Key key = KeyFactory.stringToKey(id);
	// // Bet bet = pm.getObjectById(Bet.class, key);
	// //
	// // if (bet.getStatus() != EnumBetStatus.ACTIVE)
	// // {
	// // throw new BackendException(EErrorCodes.WRONG_BET_STATUS);
	// // }
	// //
	// // if (bet != null)
	// // {
	// // bet.setActiveUntil(new Date());
	// // }
	// // }
	// // finally
	// // {
	// // pm.close();
	// // }
	// // return new ResponseStatus(true);
	// }

	// private void isBetEditor(String id) throws BackendException
	// {
	// PersistenceManager pm = PMF.get().getPersistenceManager();
	// try
	// {
	// Key key = KeyFactory.stringToKey(id);
	// UserGroup team = pm.getObjectById(UserGroup.class, key.getParent());
	// if (!isTeamEditor(pm, team))
	// {
	// throw new BackendException(EErrorCodes.NOT_TEAM_EDITOR);
	// }
	// }
	// finally
	// {
	// pm.close();
	// }
	// }
	//
	// public ResponseStatus deleteUserGroup(String id) throws
	// WebetekLoginException
	// {
	// checkLogin();
	//
	// PersistenceManager pm = PMF.get().getPersistenceManager();
	// Key key = KeyFactory.stringToKey(id);
	//
	// try
	// {
	// UserGroup ug = pm.getObjectById(UserGroup.class, key);
	// pm.deletePersistent(ug);
	//
	// return new ResponseStatus(true);
	// }
	// finally
	// {
	// pm.close();
	// }
	// }

	// public ResponseStatus deleteBetLabel(String id) throws
	// WebetekLoginException
	// {
	// // checkLogin();
	//
	// PersistenceManager pm = PMF.get().getPersistenceManager();
	//
	// Key key = KeyFactory.stringToKey(id);
	// Transaction tx = pm.currentTransaction();
	//
	// try
	// {
	// tx.begin();
	// BetLabel label = pm.getObjectById(BetLabel.class, key);
	// UserGroup team = label.getParent(pm);
	//
	// for (Bet bet : team.getBets())
	// {
	// List<Key> labels = bet.getLabels();
	// labels.remove(label.getKey());
	// }
	//
	// // delete label!
	// // pm.deletePersistent(label);
	// team.removeLabel(label);
	//
	// tx.commit();
	//
	// return new ResponseStatus(true);
	// }
	// finally
	// {
	// if (tx.isActive())
	// {
	// tx.rollback();
	// }
	// pm.close();
	// }
	//
	// }

	//
	// public ArrayList<UserBean> getPlayers(String teamid, boolean stats)
	// throws BackendException, WebetekLoginException
	// {
	// return getPlayers(teamid, stats, EnumUserStatus.ACTIVE);
	// }

	// public ArrayList<UserBean> getPlayers(String teamid, boolean stats,
	// EnumUserStatus status) throws BackendException, WebetekLoginException
	// {
	//
	// checkLogin();
	//
	// PersistenceManager pm = PMF.get().getPersistenceManager();
	// try
	// {
	// UserGroup team = extractTeam(teamid, pm);
	// Set<WebetekUser> players = team.getPlayers();
	//
	// // Query query = pm.newQuery(WebetekUser.class,
	// // "select from WebetekUser where parent == teamIdParam");
	// //
	// query.declareParameters("com.aptemo.webetek.server.data.UserGroup teamIdParam");
	// //
	// // List<WebetekUser> results = (List<WebetekUser>)
	// // query.execute(team);
	// //
	//
	// // Query qplayers = pm.newQuery("select from " +
	// // WebetekUser.class.getName() +
	// // " where parent == :p1 && status == :p2");
	// // List<WebetekUser> players = (List<WebetekUser>)
	// // qplayers.execute(team, status);
	//
	// ArrayList<UserBean> gamersbean = new ArrayList<UserBean>();
	// for (WebetekUser item : players)
	// {
	// if (status != null && !status.equals(item.getStatus()))
	// {
	// continue;
	// }
	//
	// UserBean user = item.toBean();
	//
	// // TODO optimize - very long operation!!!
	// if (stats)
	// {
	// // add statistics
	//
	// // check cache
	// String STATS_PREFIX = "STATISTICS/";
	// StatisticsBean bean = (StatisticsBean) memcache.get(STATS_PREFIX +
	// user.getKey());
	// // No cache - go langsam und siher
	// if (bean == null)
	// {
	// StatisticsUserEngine userStatistics = new
	// StatisticsUserEngine(EStatsPeriod.EALLTIME, user.getKey());
	// bean = userStatistics.calculate(pm, item);
	//
	// // store it in cache
	// memcache.put(STATS_PREFIX + user.getKey(), bean);
	// }
	//
	// user.setStatistics(bean);
	//
	// }
	//
	// gamersbean.add(user);
	// }
	//
	// return gamersbean;
	// }
	// finally
	// {
	// pm.close();
	// }
	// }
	//
	// public UserBean inviteUser(String teamId, String toEmail, String message,
	// String subject, String farewell) throws BackendException,
	// WebetekLoginException
	// {
	// checkLogin();
	//
	// PersistenceManager pm = PMF.get().getPersistenceManager();
	//
	// Transaction tx = pm.currentTransaction();
	// try
	// {
	// tx.begin();
	// UserGroup team = extractTeam(teamId, pm);
	//
	// if (!isTeamEditor(pm, team))
	// {
	// throw new BackendException(EErrorCodes.NOT_TEAM_MEMBER);
	// }
	//
	// //
	// if (isTeamMember(pm, team, toEmail, null))
	// {
	// throw new BackendException(EErrorCodes.PLAYER_EXISTS_ALREADY);
	// }
	//
	// User curus = userService.getCurrentUser();
	// if (curus == null)
	// {
	// throw new BackendException(EErrorCodes.LOGIN_ERROR);
	// }
	// String currentUser = curus.getEmail();
	// // create new user object
	// WebetekUser user = new WebetekUser(toEmail);
	// pm.makePersistent(user);
	// //
	// team.addPlayer(user.getKey());
	//
	// String content = message;
	// content += "\r\n\r\n" + team.getName() + "\r\n";
	// content += "\r\n" + team.getDescription();
	//
	// // conf link
	// String link = getServletUrl() + "/webetek/invite?id=" + user.getSid() +
	// "&method=approve";
	// content += "\r\n\r\n" + link;
	//
	// content += "\r\n\r\n" + farewell;
	//
	// content += "\r\n\r\n" + "http://webetek.appspot.com/#group-" +
	// team.getSid();
	//
	// // utils.sendEmail(currentUser, toEmail, subject, content);
	// createEmailSenderTask(user.getEmail(), toEmail, "", subject, content);
	//
	// // create user...
	// user.setStatus(EnumUserStatus.INVITED);
	//
	// tx.commit();
	// return user.toBean();
	// }
	// finally
	// {
	// if (tx.isActive())
	// {
	// tx.rollback();
	// }
	// pm.close();
	// }
	// }

	//
	// public boolean joinToGroup(String teamid, String note, String subject)
	// throws WebetekLoginException, BackendException
	// {
	// checkLogin();
	//
	// PersistenceManager pm = PMF.get().getPersistenceManager();
	//
	// Transaction tx = pm.currentTransaction();
	// try
	// {
	// tx.begin();
	//
	// String currentUser = userService.getCurrentUser().getEmail();
	// // Create new user....
	// UserBean user = createUser(currentUser, teamid, EnumUserStatus.JOINING,
	// EnumUserRole.GAMER, 0.0);
	// //
	// UserGroup team = extractTeam(teamid, pm);
	// Key ownerkey = team.getOwnerKey();
	// WebetekUser owner = pm.getObjectById(WebetekUser.class, ownerkey);
	//
	// String content = prepareContent(team, owner, user.getKey(), note,
	// subject);
	// // inform team manager...
	// // utils.sendEmail(currentUser, owner.getEmail(), subject, content);
	// createEmailSenderTask(user.getEmail(), owner.getEmail(), "", subject,
	// content);
	//
	// tx.commit();
	// }
	// finally
	// {
	// if (tx.isActive())
	// {
	// tx.rollback();
	// }
	// pm.close();
	// }
	// return true;
	//
	// }

	// private String prepareContent(UserGroup team, WebetekUser owner, String
	// playerId, String note, String subject)
	// {
	// String content = "You've received a message from " + owner.getEmail() +
	// "\n\n";
	//
	// // UserGroup team = pm.getObjectById(UserGroup.class,
	// // owner.getKey().getParent());//owner.getParent();
	// content += "\r\n\r\nOwner of: " + team.getName() + "\r\n";
	// content += "\r\n" + team.getDescription();
	//
	// content += "\n\nMessage: ";
	// content += note;
	//
	// content += "\r\n\r\n";
	// // conf link
	// // content += "\r\n\r\n" + farewell;
	// String link = getServletUrl() + "/webetek/invite?id=" + playerId;
	//
	// String approveLink = link + "&method=approve";
	// content += "You can approve player by clicking the folowing link " +
	// approveLink;
	// String rejectLink = link + "&method=reject";
	// content += "\r\n\r\nOr you can reject player here " + rejectLink;
	//
	// content += "\r\n\r\n" + "http://webetek.appspot.com/#group-" +
	// team.getSid();
	// return content;
	// }

	// public StakeBean placeBet(double amount, List<String> pickKeysStr,
	// EnumStakeType staketype) throws BackendException, WebetekLoginException
	// {
	// checkLogin();
	//
	// PersistenceManager pm = PMF.get().getPersistenceManager();
	//
	// Date hightime = new Date(System.currentTimeMillis() + getBetTreshold());
	//
	// // get payment amount
	// double totalAmount = amount;
	// if (staketype == EnumStakeType.SINGLE)
	// {
	// totalAmount = amount * pickKeysStr.size();
	// }
	//
	// Transaction tx = pm.currentTransaction();
	// try
	// {
	// if (pickKeysStr.size() == 0)
	// {
	// throw new BackendException(EErrorCodes.INVALID_NO_OF_PICKS);
	// }
	// // check bets...
	// if (isBetDuplicated(pm, pickKeysStr))
	// {
	// throw new BackendException(EErrorCodes.BET_PLACED_ALREADY);
	// }
	//
	// List<Key> pickkeys = new ArrayList<Key>();
	// Set<WebetekUser> users = new HashSet<WebetekUser>();
	//
	// // TODO make a query...
	// // Query qcountpicks = pm.newQuery("select from " +
	// // Pick.class.getName() + " where :p1.contains(id)");
	// // List<Pick> picks = (List<Pick>) qcountpicks.execute(pickkeys);
	// tx.begin();
	//
	// for (String item : pickKeysStr)
	// {
	// Key key = KeyFactory.stringToKey(item);
	//
	// // update pick count
	// Pick pick = pm.getObjectById(Pick.class, key);
	//
	// // check bet date
	// Bet bet = pick.getParent(pm);// pick.getBet();
	// UserGroup team = pm.getObjectById(UserGroup.class,
	// bet.getKey().getParent());
	// // get user
	// WebetekUser user = utils.getUser(pm, userService, team);
	// if (user == null)
	// {
	// throw new BackendException(EErrorCodes.NOT_TEAM_MEMBER);
	// }
	//
	// double curBal = user.getBalance();
	// // check balance and limits
	// if ((curBal - totalAmount) < user.getLimit())
	// {
	// throw new BackendException(EErrorCodes.STAKE_BALANCE_EXCEEDED);
	// }
	//
	// // check min/max
	// // UserGroup team = bet.getParent();
	// Double min = team.getMinimumStake() * pickKeysStr.size();
	// Double max = team.getMaximumStake() * pickKeysStr.size();
	// if (totalAmount < min || totalAmount > max)
	// {
	// throw new BackendException(EErrorCodes.STAKE_LIMIT_EXCEEDED);
	// }
	//
	// // check if bet is already
	// if (isBetPlaced(pm, user, bet) && !team.getAllowDuplicateBets())
	// {
	// throw new BackendException(EErrorCodes.BET_PLACED_ALREADY);
	// }
	//
	// // check date...
	// Date betDate = bet.getDate();
	// if (betDate.before(hightime))
	// {
	// throw new BackendException(EErrorCodes.STAKE_DATE_EXCEEDED);
	// }
	// // check bet status
	// if (bet.getStatus() != EnumGameStatus.ACTIVE)
	// {
	// throw new BackendException(EErrorCodes.WRONG_BET_STATUS, "CLOSED");
	// }
	//
	// // update balance
	// pick.incrementPicked();
	//
	// pickkeys.add(key);
	//
	// // remember user
	// users.add(user);
	// }
	// tx.commit();
	//
	// // update odds...
	// tx.begin();
	// updatePickOdds(pickKeysStr);
	// tx.commit();
	//
	// tx.begin();
	// // TODO stake for one user only!!! Separate stakes by teams / one
	// // stake couldn't contains picks from different teams
	// // link placed bet with user
	// Stake stake = new Stake(amount, pickkeys, staketype);
	// // TODO How to save Pick snapshot (odds)?
	//
	// for (WebetekUser user : users)
	// {
	// user.addStake(stake);
	//
	// // double curBal = user.getBalance();
	// // // that's it
	// // double newBalance = curBal - payment;
	// // user.setBalance(newBalance);
	// Payment pay = new Payment(-totalAmount, "Placing bet...",
	// EnumPaymentType.BET);
	// user.addPayment(pay);
	//
	// // send notifications...
	// sendPlaceBetNotification(pm, user, pickkeys, totalAmount, amount);
	// }
	//
	// stake.setStatus(EnumStakeStatus.OPENED);
	//
	// tx.commit();
	//
	// return stake.toBean();
	// }
	// finally
	// {
	// if (tx.isActive())
	// {
	// tx.rollback();
	// }
	// pm.close();
	//
	// }
	//
	// }
	//
	// private void updatePickOdds(List<String> pickKeysStr)
	// {
	// PersistenceManager pm = PMF.get().getPersistenceManager();
	// try
	// {
	// for (String item : pickKeysStr)
	// {
	// Key key = KeyFactory.stringToKey(item);
	//
	// // update pick count
	// // Pick stakepick = pm.getObjectById(Pick.class, key);
	// //
	// Bet bet = pm.getObjectById(Bet.class, key.getParent());//
	// stakepick.getBet();
	// double odds = 0.0;
	// // update all affected bet picks...
	// int allpicks = bet.getPickedSum();
	//
	// for (Pick pick : bet.getPicks())
	// {
	// int pickedcount = pick.getPicked();
	//
	// if (pickedcount == 0)
	// {
	// pick.setOdds(Double.POSITIVE_INFINITY);
	// continue;
	// }
	//
	// // pickedcount++;
	// // allpicks++;
	//
	// // avoid division by zero
	// odds = (allpicks + 0.0) / (pickedcount);
	//
	// DecimalFormat twoDForm = new DecimalFormat("#.##");
	// double normodds = Double.valueOf(twoDForm.format(odds));
	//
	// pick.setOdds(normodds);
	// }
	//
	// }
	// }
	// finally
	// {
	// pm.close();
	// }
	// }
	//
	// private void sendPlaceBetNotification(PersistenceManager pm, WebetekUser
	// user, List<Key> pickkeys, double payment, double amount)
	// {
	// // TODO Add to task...
	// // send notifications
	// UserGroup team = pm.getObjectById(UserGroup.class,
	// user.getKey().getParent()); // user.getParent();
	// if (team.getPlaceBetNotifications())
	// {
	// // send email...
	// String content = "";
	// content += "\r\n\r\n" + team.getName() + "\r\n";
	// content += "(" + team.getDescription() + ")";
	//
	// //
	// content += "\r\n\r\nUser: " + user.getEmail();
	// content += "\r\nPayment per bet: " + amount;
	// content += "\r\nPayment sum: " + payment;
	// content += "\r\n\r\n";
	// int i = 0;
	// for (Key key : pickkeys)
	// {
	// i++;
	// Pick pick = pm.getObjectById(Pick.class, key);
	// content += "\r\n\r\n" + i + ". ------------------------------";
	//
	// Bet bet = pm.getObjectById(Bet.class, key.getParent());
	// content += "\r\n    Game Title: " + bet.getTitle();
	// content += "\r\n    Your Pick: " + pick.getTitle();
	// content += "\r\n    Odds: " + pick.getOdds();
	// }
	//
	// //
	// content += "\r\n\r\n";
	// content += "\r\n\r\n" + "http://webetek.appspot.com/#group-" +
	// team.getSid();
	//
	// // get owner...
	// String ownerEmail = team.getOwnerEmail();
	// if (ownerEmail != null)
	// {
	// String toEmail = ownerEmail;
	// String ccEmail = "";
	// // add user...
	// if (!user.getEmail().equals(ownerEmail))
	// {
	// ccEmail = user.getEmail();
	// }
	// //
	// String subject = "[Webetek - " + team.getName() + "] New bet placed";
	// createEmailSenderTask(user.getEmail(), toEmail, ccEmail, subject,
	// content);
	// }
	// else
	// {
	// log.log(Level.WARNING, "Cannot extract team owner!");
	// }
	// }
	//
	// }

	private WebetekUser extractTeamOwner(PersistenceManager pm, UserGroup team)
	{
		WebetekUser user = pm.getObjectById(WebetekUser.class, team.getOwnerKey());
		return user;
	}

	// private boolean isBetDuplicated(PersistenceManager pm, List<String>
	// pickKeysStr)
	// {
	//
	// List<Bet> bets = new ArrayList<Bet>();
	// for (String item : pickKeysStr)
	// {
	// Key key = KeyFactory.stringToKey(item);
	//
	// // update pick count
	// Pick pick = pm.getObjectById(Pick.class, key);
	//
	// // check bet date
	// Bet bet = pick.getParent(pm);
	// if (bet.getParent(pm).getAllowDuplicateBets())
	// {
	// return false;
	// }
	// if (bets.contains(bet))
	// {
	// return true;
	// }
	// bets.add(bet);
	// }
	// return false;
	// }

	private boolean isBetPlaced(PersistenceManager pm, WebetekUser user, Bet bet)
	{
		//
		for (Stake stake : user.getStakes())
		{
			for (Key key : stake.getPickKeys())
			{
				Pick pick = pm.getObjectById(Pick.class, key);
				Bet pbet = pick.getParent(pm);
				if (bet.equals(pbet))
				{
					return true;
				}
			}
		}
		return false;
	}

	// private void updatePickOdds(PersistenceManager pm, Stake stake)
	// {
	// for (Key key : stake.getPickKeys())
	// {
	// Pick stakepick = pm.getObjectById(Pick.class, key);
	// Bet bet = stakepick.getBet();
	//
	// double odds = 0.0;
	// // update all affected bet picks...
	// int allpicks = bet.getPickedSum();
	// for (Pick pick : bet.getPicks())
	// {
	// int pickedcount = pick.getPicked();
	//
	// if (pickedcount == 0)
	// {
	// pick.setOdds(Double.POSITIVE_INFINITY);
	// continue;
	// }
	//
	// // pickedcount++;
	// // allpicks++;
	//
	// // avoid division by zero
	// odds = (allpicks + 0.0) / (pickedcount);
	//
	// DecimalFormat twoDForm = new DecimalFormat("#.##");
	// double normodds = Double.valueOf(twoDForm.format(odds));
	//
	// pick.setOdds(normodds);
	// }
	// }
	// }
	//
	// public ArrayList<StakeBean> getStakes(EnumStakeStatus status) throws
	// WebetekLoginException
	// {
	// // checkLogin();
	//
	// PersistenceManager pm = PMF.get().getPersistenceManager();
	// try
	// {
	// List<WebetekUser> users = utils.getUser(pm, userService);
	//
	// ArrayList<StakeBean> stakebeans = new ArrayList<StakeBean>();
	// for (WebetekUser user : users)
	// {
	// for (Stake stake : user.getStakes())
	// {
	// // if (status == stake.getStatus())
	// {
	// stakebeans.add(stake.toBean());
	// }
	// }
	//
	// }
	// return stakebeans;
	// }
	// finally
	// {
	// pm.close();
	// }
	// }
	//
	// public ArrayList<StakeBean> getStakes4Team(String teamId, EnumStakeStatus
	// status) throws WebetekLoginException, BackendException
	// {
	// checkLogin();
	//
	// PersistenceManager pm = PMF.get().getPersistenceManager();
	// try
	// {
	// UserGroup team = extractTeam(teamId, pm);
	//
	// WebetekUser user = utils.getUser(pm, userService, team);
	//
	// ArrayList<StakeBean> stakebeans = new ArrayList<StakeBean>();
	// if (user == null)
	// {
	// return stakebeans;
	// }
	//
	// for (Stake stake : user.getStakes())
	// {
	// if (status == null || status == stake.getStatus())
	// {
	// stakebeans.add(stake.toBean());
	// }
	// }
	// return stakebeans;
	// }
	// finally
	// {
	// pm.close();
	// }
	// }

	// public ResponseStatus deleteStake(String id) throws BackendException
	// {
	// PersistenceManager pm = PMF.get().getPersistenceManager();
	//
	// Transaction tx = pm.currentTransaction();
	// try
	// {
	//
	// Key key = KeyFactory.stringToKey(id);
	// Stake stake = pm.getObjectById(Stake.class, key);
	//
	// // check status
	// if (stake.getStatus() == EnumStakeStatus.CLOSED)
	// {
	// throw new BackendException(EErrorCodes.STAKE_WRONG_STATUS);
	// }
	//
	// tx.begin();
	// // update pick counter
	// for (Key pickkey : stake.getPickKeys())
	// {
	// Pick pick = pm.getObjectById(Pick.class, pickkey);
	// pick.decrementPicked();
	// }
	//
	// pm.deletePersistentAll(stake);
	//
	// tx.commit();
	// }
	// finally
	// {
	// if (tx.isActive())
	// {
	// tx.rollback();
	// }
	// pm.close();
	// }
	// return null;
	// }

	// public UserBean createUser(String email, String groupid) throws
	// BackendException, WebetekLoginException
	// {
	// return createUser(email, groupid, EnumUserStatus.CREATED, EnumRole.GAMER,
	// 0.0);
	// }

	// public UserBean createUser(String email, String groupid, EnumUserStatus
	// status, EnumRole role, double initialBalance) throws BackendException,
	// WebetekLoginException
	// {
	// checkLogin();
	//
	// PersistenceManager pm = PMF.get().getPersistenceManager();
	// try
	// {
	// UserGroup team = extractTeam(groupid, pm);
	// // checkRole() do not. see Join
	// // isTeamEditor(pm, team);
	// //
	// // check all statuses
	// if (isTeamMember(pm, team, email, null))
	// {
	// throw new BackendException(EErrorCodes.PLAYER_EXISTS_ALREADY);
	// }
	//
	// WebetekUser user = new WebetekUser(email);
	// user.setRole(role);
	//
	// user.setStatus(status);
	//
	// // user.setBalance(initialBalance);
	// if (initialBalance != 0)
	// {
	// Payment payment = new Payment(initialBalance, "Initial balance...",
	// EPaymentType.PAYMENT);
	// user.addPayment(payment);
	// }
	// // add to team...
	// team.addPlayer(user);
	//
	// return user.toBean();
	// }
	// finally
	// {
	// pm.close();
	// }
	// }
	//
	// public UserBean createAdminUser(String email)
	// {
	// WebetekUser user = new WebetekUser(email);
	// user.setRole(EnumRole.ADMIN);
	// user.setStatus(EnumUserStatus.ACTIVE);
	// // user.setBalance(10);
	//
	// PersistenceManager pm = PMF.get().getPersistenceManager();
	// try
	// {
	//
	// // create new admin team or get one
	// UserGroup temp = getAdminGroup();
	// UserGroup team = pm.getObjectById(UserGroup.class, temp.getKey());
	//
	// // pm.makePersistent(user);
	//
	// team.addPlayer(user);
	// team.setOwnerKey(user.getKey());
	// team.setOwnerEmail(user.getEmail());
	//
	// // UserGroup group = new UserGroup("Test");
	// // group.setPublic(true);
	// // group.setDescription("Test");
	// // group.addPlayer(user.getKey());
	// // pm.makePersistent(group);
	//
	// return user.toBean();
	//
	// }
	// finally
	// {
	// pm.close();
	// }
	// }

	// public GameBean assignResult(String pickkey, String comment) throws
	// BackendException, WebetekLoginException
	// {
	// checkLogin();
	//
	// PersistenceManager pm = PMF.get().getPersistenceManager();
	//
	// try
	// {
	//
	// if ((null == pickkey) || (pickkey.isEmpty()))
	// {
	// throw new BackendException(EErrorCodes.INVALID_ID, "PickId");
	// }
	//
	// Key pkey = KeyFactory.stringToKey(pickkey);
	// // check if the pick doesn't belong to given bet!!!
	// if ((null == pkey))
	// {
	// throw new BackendException(EErrorCodes.INVALID_ID, "PickId");
	// }
	// Pick winpick = pm.getObjectById(Pick.class, pkey);
	//
	// // extract bet and assign result
	// Bet bet = winpick.getParent(pm);
	// UserGroup team = bet.getParent(pm);
	//
	// if (!isTeamEditor(pm, team))
	// {
	// throw new BackendException(EErrorCodes.NOT_TEAM_OWNER);
	// }
	//
	// if ((bet.getStatus() != EnumGameStatus.WAITINGRESULTS) &&
	// (!userService.isUserAdmin()))
	// {
	// throw new BackendException(EErrorCodes.WRONG_BET_STATUS,
	// "Wrong bet state [" + bet.getStatus() + "]!");
	// }
	//
	// // ///////////////////////////////////////////////
	// // update pick status
	// for (Pick betpick : bet.getPicks())
	// {
	// if (betpick.equals(winpick))
	// {
	// // apply PICK status
	// betpick.setStatus(EnumPickStatus.WON);
	// }
	// else
	// {
	// // apply PICK status
	// betpick.setStatus(EnumPickStatus.LOOSE);
	// }
	// }
	//
	// // ///////////////////////////////////////////////
	// // close relevant stakes and calculate earnings...
	// // TODO:: add task
	// // updateStakesStatus(pm, team);
	//
	// for (WebetekUser user : team.getPlayers())
	// {
	// // trigger user statistics tasks indirectly from updateStake
	// // task...
	// createUpdateStakeTask(user.getSid());
	// }
	//
	// bet.setStatus(EnumGameStatus.CLOSED);
	// bet.setResultDescription(comment);
	// return bet.toBean();
	// }
	// finally
	// {
	// pm.close();
	// }
	// }

	// private void updateStakesStatus(PersistenceManager pm, UserGroup team)
	// {
	// //
	// for (WebetekUser player : team.getPlayers())
	// {
	// for (Stake stake : player.getStakes())
	// {
	// boolean stakeIncompleted = false;
	// double earnings = 0.0;
	//
	// if (stake.getStatus() == EnumStakeStatus.OPENED)
	// {
	// List<Key> keys = stake.getPickKeys();
	// // if (keys.contains(winpick.getId()))
	// {
	// for (Key key : keys)
	// {
	// Pick pick = pm.getObjectById(Pick.class, key);
	// if (pick.getStatus() == EnumPickStatus.NONE)
	// {
	// // not all bets (picks) closed...
	// // reset earnings...
	// stake.setEarnings(0.0);
	// stakeIncompleted = true;
	// break;
	// }
	//
	// if (pick.getStatus() == EnumPickStatus.WON)
	// {
	// earnings += pick.getOdds() * stake.getAmount();
	// }
	//
	// }
	// if (stakeIncompleted == false)
	// {
	// // update stake
	// stake.setStatus(EnumStakeStatus.CLOSED);
	//
	// if (Double.isInfinite(earnings) || Double.isNaN(earnings))
	// {
	// log.severe("Wrong Stake earnings calculation!!! amount=" +
	// stake.getAmount());
	// }
	// else
	// {
	// stake.setEarnings(earnings);
	// }
	// }
	// }
	//
	// }
	//
	// }
	//
	// }
	// }

	// public UserGroupBean createUserGroup(String name, String description,
	// String email, boolean isPublic) throws BackendException,
	// WebetekLoginException
	// public TeamBean createUserGroup(TeamBean bean) throws BackendException,
	// WebetekLoginException
	// {
	// checkLogin();
	// if (!userService.isUserAdmin())
	// {
	// throw new WebetekLoginException("Not an admin", "");
	// }
	// // create team...
	// UserGroup team = new UserGroup(bean.getName());
	// team.setPublic(bean.isPublic());
	// team.setDescription(bean.getDescription());
	// team.setPlaceBetNotifications(bean.isPlaceBetNotifications());
	// team.setTeamRules(bean.getTeamRules());
	// if (bean.getMinStake() == null)
	// {
	// team.setMinimumStake(bean.getMinStake());
	// }
	// else
	// {
	// team.setMinimumStake(bean.getMinStake());
	// }
	// if (bean.getMaxStake() == null)
	// {
	// team.setMaximumStake(Double.MAX_VALUE);
	// }
	// else
	// {
	// team.setMaximumStake(bean.getMaxStake());
	// }
	//
	// // create owner/editor
	// WebetekUser owner = new WebetekUser(bean.getOwnerEmail());
	// owner.setRole(EnumRole.EDITOR);
	// owner.setStatus(EnumUserStatus.ACTIVE);
	//
	// PersistenceManager pm = PMF.get().getPersistenceManager();
	// try
	// {
	// pm.makePersistent(team);
	// team.addPlayer(owner);
	// team.setOwnerKey(owner.getKey());
	// team.setOwnerEmail(owner.getEmail());
	// return team.toBean();
	// }
	// finally
	// {
	// pm.close();
	// }
	//
	// }
	//
	// public ArrayList<TeamBean> getUserGroups(boolean mineonly) throws
	// WebetekLoginException
	// {
	// // checkLogin();
	//
	// PersistenceManager pm = PMF.get().getPersistenceManager();
	// try
	// {
	// String email = "guest";
	// boolean privateToo = false;
	// if (userService.getCurrentUser() != null)
	// {
	// email = userService.getCurrentUser().getEmail();
	//
	// if (userService.isUserAdmin())
	// {
	// privateToo = true;
	// }
	// }
	//
	// List<UserGroup> groups;
	// Query query = pm.newQuery(UserGroup.class);
	// groups = (List<UserGroup>) query.execute();
	//
	// ArrayList<TeamBean> beans = new ArrayList<TeamBean>();
	// for (UserGroup item : groups)
	// {
	// boolean check = false;
	// // filter by owner
	// Key key = item.getOwnerKey();
	// if (key != null)
	// {
	// WebetekUser owner = null;
	// owner = pm.getObjectById(WebetekUser.class, key);
	// check = (owner != null && owner.getEmail().equals(email));
	// }
	// if ((check && mineonly) || privateToo || (!mineonly && item.isPublic()))
	// {
	// beans.add(item.toBean());
	// }
	// }
	//
	// return beans;
	// }
	// finally
	// {
	// pm.close();
	// }
	// }

	// public UserGroupBean modifyUserGroup(String id, String name, String
	// description, String ownerEmail, boolean isPublic, String rules, Double
	// minStake,
	// Double maxStake, Boolean notifications) throws BackendException,
	// WebetekLoginException
	// public TeamBean modifyUserGroup(TeamBean bean) throws BackendException,
	// WebetekLoginException
	// {
	// checkLogin();
	//
	// PersistenceManager pm = PMF.get().getPersistenceManager();
	// try
	// {
	// UserGroup team = extractTeam(bean.getId(), pm);
	//
	// changeTeamOwner(bean.getOwnerEmail(), team.getSid());
	//
	// // update object...
	// team.setName(bean.getName());
	// team.setPublic(bean.isPublic());
	// team.setDescription(bean.getDescription());
	// team.setTeamRules(bean.getTeamRules());
	// team.setMinimumStake(bean.getMinStake());
	// team.setMaximumStake(bean.getMaxStake());
	// team.setPlaceBetNotifications(bean.isPlaceBetNotifications());
	//
	// return team.toBean();
	//
	// }
	// finally
	// {
	// pm.close();
	// }
	// }
	//
	// public TeamBean getUserGroupDetails(String id) throws BackendException,
	// WebetekLoginException
	// {
	// // checkLogin();
	//
	// PersistenceManager pm = PMF.get().getPersistenceManager();
	// try
	// {
	// UserGroup group = extractTeam(id, pm);
	//
	// // if (!isTeamMember(pm, group))
	// // {
	// // throw new BackendException("Not a team member!");
	// // }
	//
	// TeamBean bean = group.toBean();
	//
	// // // Assign requesting user
	// // WebetekUser user = utils.getUser(pm, userService, group);
	// // if (user != null)
	// // {
	// // bean.setRole(user.getRole());
	// //
	// // bean.setRequestUser(user.getSid());
	// // }
	// return bean;
	// }
	// finally
	// {
	// pm.close();
	// }
	// }
	//
	// public GameBean getBetDetails(String id)
	// {
	// return dbAPI.getGame(id);
	//
	// // PersistenceManager pm = PMF.get().getPersistenceManager();
	// // try
	// // {
	// // Key key = KeyFactory.stringToKey(id);
	// // Bet bet = pm.getObjectById(Bet.class, key);
	// //
	// // // try
	// // // {
	// // // findStakes4Bet(bet.getSid());
	// // // }
	// // // catch (WebetekLoginException e)
	// // // {
	// // // // TODO Auto-generated catch block
	// // // e.printStackTrace();
	// // // }
	// //
	// // GameBean bean = bet.toBean();
	// //
	// // // WebetekUser user = utils.getUser(pm, userService,
	// // // bet.getParent());
	// // // bean.setRole(user.getRole());
	// // return bean;
	// // }
	// // finally
	// // {
	// // pm.close();
	// // }
	// }

	public PickBean getPickDetails(String id)
	{
		PersistenceManager pm = PMF.get().getPersistenceManager();
		try
		{
			Key key = KeyFactory.stringToKey(id);
			Pick pick = pm.getObjectById(Pick.class, key);
			Bet bet = pick.getParent(pm);
			return pick.toBean(bet.toBean());
		}
		finally
		{
			pm.close();
		}
	}

	// public GetPlayersResponse getUsers(EnumUserStatus status) throws
	// WebetekLoginException
	// {
	// // checkLogin();
	//
	// ArrayList<UserBean> gamersbean = new ArrayList<UserBean>();
	//
	// PersistenceManager pm = PMF.get().getPersistenceManager();
	// try
	// {
	//
	// // get gamers...
	// Query query = pm.newQuery(WebetekUser.class);
	// query.setFilter("status == idStatus");
	// query.declareParameters("com.aptemo.webetek.client.enums.EnumUserStatus idStatus");
	// //
	// List<WebetekUser> users = (List<WebetekUser>) query.execute(status);
	//
	// for (WebetekUser item : users)
	// {
	// gamersbean.add(item.toBean());
	// }
	//
	// return new GetPlayersResponse(gamersbean);
	// }
	// finally
	// {
	// pm.close();
	// }
	// }

	public ArrayList<LabelBean> getBetLabels(String teamId) throws WebetekLoginException, BackendException
	{
		// checkLogin();

		ArrayList<LabelBean> labels = new ArrayList<LabelBean>();

		PersistenceManager pm = PMF.get().getPersistenceManager();
		try
		{

			UserGroup team = extractTeam(teamId, pm);
			// get labels...
			for (BetLabel item : team.getLabels())
			{
				labels.add(item.toBean());
			}

			return labels;
		}
		finally
		{
			pm.close();
		}
	}

	//
	// public UserBean modifyPlayer(UserBean user) throws WebetekLoginException
	// {
	// checkLogin();
	//
	// return dbAPI.modifyPlayer(user);
	//
	// // PersistenceManager pm = PMF.get().getPersistenceManager();
	// // try
	// // {
	// //
	// // Key key = KeyFactory.stringToKey(user.getKey());
	// // WebetekUser player = pm.getObjectById(WebetekUser.class, key);
	// //
	// // player.setStatus(user.getStatus());
	// // player.setRole(user.getRole());
	// // if (userService.isUserAdmin())
	// // {
	// // player.setBalance(user.getBalance());
	// // }
	// //
	// // return player.toBean();
	// // }
	// // finally
	// // {
	// // pm.close();
	// // }
	// }
	//
	// public boolean deletePlayer(String id) throws WebetekLoginException,
	// BackendException
	// {
	// checkLogin();
	//
	// return dbAPI.deletePlayer(id);
	//
	// // PersistenceManager pm = PMF.get().getPersistenceManager();
	// // try
	// // {
	// //
	// // Key key = KeyFactory.stringToKey(id);
	// // WebetekUser player = pm.getObjectById(WebetekUser.class, key);
	// //
	// // // Key tkey = KeyFactory.stringToKey(teamid);
	// // // UserGroup team = pm.getObjectById(UserGroup.class, tkey);
	// // UserGroup team = player.getParent();
	// //
	// // // owner check
	// // if (key.equals(team.getOwnerKey()))
	// // {
	// // throw new BackendException(EErrorCodes.DO_NOT_REMOVE_OWNER);
	// // }
	// //
	// // team.removePlayer(player);
	// //
	// // return true;
	// // }
	// // finally
	// // {
	// // pm.close();
	// // }
	// }

	// public UserBean changeTeamOwner(String email, String groupid) throws
	// BackendException
	// {
	//
	// PersistenceManager pm = PMF.get().getPersistenceManager();
	// try
	// {
	// UserGroup team = extractTeam(groupid, pm);
	//
	// WebetekUser user = null;
	//
	// if (email == null || email.isEmpty())
	// {
	// throw new BackendException(EErrorCodes.INVALID_OWNER_DATA);
	// }
	//
	// // check if owner is one of the team players
	// Set<WebetekUser> players = team.getPlayers();
	// for (WebetekUser player : players)
	// {
	// // revert status
	// if (player.getRole() == EnumRole.EDITOR)
	// {
	// player.setRole(EnumRole.GAMER);
	// }
	// if (player.getEmail().equals(email))
	// {
	// user = player;
	// }
	//
	// }
	// // still null? create new player/owner
	// if (user == null)
	// {
	// user = new WebetekUser(email);
	// team.addPlayer(user);
	// }
	//
	// user.setRole(EnumRole.EDITOR);
	// team.setOwnerKey(user.getKey());
	// team.setOwnerEmail(user.getEmail());
	//
	// return user.toBean();
	// }
	// finally
	// {
	// pm.close();
	// }
	// }

	// public LabelBean createLabel(String labelName, String teamId) throws
	// BackendException, WebetekLoginException
	// {
	// // checkLogin();
	//
	// PersistenceManager pm = PMF.get().getPersistenceManager();
	// try
	// {
	// UserGroup team = extractTeam(teamId, pm);
	//
	// BetLabel label = new BetLabel(labelName);
	// team.addLabel(label);
	//
	// // bet.addLabel(label.getKey());
	//
	// return label.toBean();
	// }
	// finally
	// {
	// pm.close();
	// }
	// }

	// private void manageStakes(String email) throws WebetekLoginException
	// {
	// PersistenceManager pm = PMF.get().getPersistenceManager();
	// try
	// {
	// List<WebetekUser> users = utils.getUser(pm, userService);
	//
	// for (WebetekUser user : users)
	// {
	// for (Stake stake : user.getStakes())
	// {
	// //
	// List<Key> keys = stake.getPickKeys();
	// for (Key key : keys)
	// {
	//
	// Pick pick = pm.getObjectById(Pick.class, key);
	// Bet bet = pick.getBet();
	//
	// if (bet.getResult() != null)
	// {
	// if (key == bet.getResult().getPickKey())
	// {
	// // win
	// }
	// else
	// {
	// // loose
	// }
	// }
	// }
	//
	// }
	//
	// }
	// }
	// finally
	// {
	// pm.close();
	// }
	// }

	// /**
	// * Called after the bet is placed...
	// */
	// public void updateOdds(StakeBean stake)
	// {
	// PersistenceManager pm = PMF.get().getPersistenceManager();
	// try
	// {
	//
	// List<Key> pickkeys = new ArrayList<Key>();
	//
	// for (PickBean item : stake.getPicks())
	// {
	// String id = item.getId();
	// Key key = KeyFactory.stringToKey(id);
	// if (key != null)
	// {
	// pickkeys.add(key);
	// }
	// else
	// {
	// // TODO what now???
	// }
	// }
	//
	// // update pick odds and possible winnings
	// for (Key key : pickkeys)
	// {
	// double odds = 0.0;
	//
	// // retrieve pick
	// Pick stakepick = pm.getObjectById(Pick.class, key);
	// Bet bet = stakepick.getBet();
	//
	// // update all affected bet picks...
	// int allpicks = bet.getPickedSum();
	// for (Pick pick : bet.getPicks())
	// {
	// int pickedcount = pick.getPicked();
	//
	// pickedcount++;
	// allpicks++;
	//
	// // avoid division by zero
	// odds = (allpicks + 0.0) / (pickedcount);
	//
	// DecimalFormat twoDForm = new DecimalFormat("#.##");
	// double normodds = Double.valueOf(twoDForm.format(odds));
	//
	// pick.setOdds(normodds);
	// }
	// }
	// }
	// finally
	// {
	// pm.close();
	// }
	// }

	// public List<BetBean> getStakes4Bet(String betkey) throws
	// WebetekLoginException
	// {
	// // checkLogin();
	//
	// List<BetBean> matchedStakes = new ArrayList<BetBean>();
	// PersistenceManager pm = PMF.get().getPersistenceManager();
	// try
	// {
	// Bet bet = pm.getObjectById(Bet.class, betkey);
	//
	// WebetekUser user = utils.getUser(pm, userService, bet.getParent(pm));
	//
	// Query q = pm.newQuery("select id from " + Pick.class.getName() +
	// " where parentKey == :p1");
	// List<Key> pkeys = (List<Key>) q.execute(bet.getKey());
	//
	// Query query = pm.newQuery(Stake.class);
	// query.setFilter("parentKey == :p1 && pickKeys.contains(:p2)");
	//
	// List<Stake> res = (List<Stake>) query.execute(user.getKey(), pkeys);
	// for (Stake stake : res)
	// {
	// matchedStakes.add(stake.toBean());
	// }
	//
	// // List<Stake> stakes = user.getStakes();
	// // for (Stake stake : stakes)
	// // {
	// // List<Key> picks = stake.getPickKeys();
	// // for (Key pickkey : picks)
	// // {
	// // Pick pick = pm.getObjectById(Pick.class, pickkey);
	// // if (pick.getParent(pm).equals(bet))
	// // {
	// // matchedStakes.add(stake.toBean());
	// // }
	// // }
	// // }
	// return matchedStakes;
	// }
	// finally
	// {
	// pm.close();
	// }
	// }

	private int getNoOfUsers()
	{
		PersistenceManager pm = PMF.get().getPersistenceManager();
		try
		{
			Query query = pm.newQuery(WebetekUser.class);
			int users = ((List<WebetekUser>) query.execute()).size();

			return users;
		}
		finally
		{
			pm.close();
		}
	}

	private int getNoOfTeamUsers(String teamid)
	{
		int players = 0;
		PersistenceManager pm = PMF.get().getPersistenceManager();
		try
		{
			Key key = KeyFactory.stringToKey(teamid);

			UserGroup team = pm.getObjectById(UserGroup.class, key);

			if (team != null)
			{
				team.getPlayers().size();
			}
			return players;
		}
		finally
		{
			pm.close();
		}
	}

	public StatisticsBean getAppStatistics(EStatsPeriod period)
	{
		StatisticsBean stats = new StatisticsBean();

		PersistenceManager pm = PMF.get().getPersistenceManager();
		try
		{
			int noofusers = getNoOfUsers();

			Query query2 = pm.newQuery(Bet.class);
			query2.setFilter("status == statusParam && activeUntil == NULL");
			query2.declareParameters(EnumEventStatus.class.getName() + " statusParam");
			// query2.declareParameters("java.util.Date dateParam");
			List<Bet> bets = (List<Bet>) query2.execute(EnumEventStatus.ACTIVE);

			Query queryAllBets = pm.newQuery(Bet.class);
			List<Bet> allbets = (List<Bet>) queryAllBets.execute();

			Query query3 = pm.newQuery(UserGroup.class);
			List<UserGroup> teams = (List<UserGroup>) query3.execute();

			stats.setNoOfUsers(noofusers);
			stats.setNoOfTeams(teams.size());
			stats.setNoOfActiveBets(bets.size());
			stats.setNoOfAllBets(allbets.size());

			return stats;
		}
		finally
		{
			pm.close();
		}
	}

	public StatisticsBean getTeamStatistics(EStatsPeriod period, String teamid)
	{
		StatisticsBean stats = new StatisticsBean();

		stats.setNoOfUsers(getNoOfTeamUsers(teamid));

		return stats;
	}

	public StatisticsBean getUserStatistics(EStatsPeriod period, String teamid) throws WebetekLoginException, BackendException
	{

		// checkLogin();

		PersistenceManager pm = PMF.get().getPersistenceManager();

		try
		{
			Key key = KeyFactory.stringToKey(teamid);
			UserGroup team = pm.getObjectById(UserGroup.class, key);

			WebetekUser user = utils.getUser(pm, userService, team);
			if (user == null)
			{
				throw new BackendException(EErrorCodes.NOT_TEAM_MEMBER);
			}
			// TODO later calculate stats bean on login and pass the object...
			StatisticsUserEngine userStatistics = new StatisticsUserEngine(period, user.getSid());
			return userStatistics.calculate(pm, user);
		}
		finally
		{
			pm.close();
		}

	}

	// public UserBean addPayment(String userId, String teamId, double amount,
	// EPaymentType type) throws WebetekLoginException, BackendException
	// {
	// PersistenceManager pm = PMF.get().getPersistenceManager();
	//
	// checkLogin();
	//
	// try
	// {
	// WebetekUser player = null;
	// if (userId == null)
	// {
	// Key key = KeyFactory.stringToKey(teamId);
	// UserGroup team = pm.getObjectById(UserGroup.class, key);
	// player = utils.getUser(pm, userService, team);
	// }
	// else
	// {
	// Key key = KeyFactory.stringToKey(userId);
	// player = pm.getObjectById(WebetekUser.class, key);
	// }
	//
	// if (player != null)
	// {
	// // WebetekUser user = utils.getUser(pm, userService,
	// // player.getParent());
	// if (!isTeamOwner(pm, teamId))
	// {
	// throw new BackendException(EErrorCodes.NOT_TEAM_OWNER);
	// }
	//
	// // set balance
	// // double curbal = player.getBalance();
	// // player.setBalance(curbal + amount);
	//
	// Payment payment = new Payment(amount, "User payment: " + amount, type);
	// player.addPayment(payment);
	// }
	//
	// return player.toBean();
	// }
	// finally
	// {
	// pm.close();
	// }
	// }
	//
	// public List<PaymentBean> getPayments(String teamId) throws
	// BackendException, WebetekLoginException
	// {
	// checkLogin();
	//
	// PersistenceManager pm = PMF.get().getPersistenceManager();
	// try
	// {
	// UserGroup team = extractTeam(teamId, pm);
	//
	// if (!isTeamMember(pm, team))
	// {
	// throw new BackendException(EErrorCodes.NOT_TEAM_MEMBER);
	// }
	//
	// WebetekUser user = utils.getUser(pm, userService, team);
	//
	// ArrayList<PaymentBean> paymentbeans = new ArrayList<PaymentBean>();
	// for (Payment payment : user.getPayments())
	// {
	// // if (status == stake.getStatus())
	// {
	// paymentbeans.add(payment.toBean());
	// }
	//
	// }
	// return paymentbeans;
	// }
	// finally
	// {
	// pm.close();
	// }
	// }
	//
	// private void closeUserStakes(PersistenceManager pm, WebetekUser user)
	// {
	//
	// List<Stake> stakes = user.getStakes();
	//
	// for (Stake stake : stakes)
	// {
	// if (stake.getStatus() == EnumStakeStatus.OPENED)
	// {
	// // calculate winnings...
	// double won = calculateWinnings(pm, stake);
	//
	// stake.setEarnings(won);
	//
	// stake.setStatus(EnumStakeStatus.CLOSED);
	// }
	// }
	//
	// }
	//
	// private double calculateWinnings(PersistenceManager pm, Stake stake)
	// {
	// // TODO check stake type (system/single/...)
	//
	// List<Key> keys = stake.getPickKeys();
	//
	// double part = 0.0;
	// for (Key key : keys)
	// {
	// Pick pick = pm.getObjectById(Pick.class, key);
	//
	// Bet bet = pick.getParent(pm);
	//
	// int allpicks = bet.getPickedSum();
	//
	// int pickedcnt = pick.getPicked();
	//
	// double odds = (allpicks + 0.0) / pickedcnt;
	//
	// switch (stake.getBetType())
	// {
	// // case SINGLE:
	// // part += odds;
	// // break;
	// // case SYSTEM:
	// // part *= odds;
	// // break;
	// default:
	// part += odds;
	//
	// }
	//
	// }
	//
	// //
	// double result = part * stake.getAmount();
	//
	// return result;
	// }

	public WebetekUser getCurrentUserInfo(String teamId) throws BackendException
	{
		PersistenceManager pm = PMF.get().getPersistenceManager();
		try
		{
			UserGroup team = extractTeam(teamId, pm);

			WebetekUser user = utils.getUser(pm, userService, team);
			return user;

		}
		finally
		{
			pm.close();
		}
	}

	//
	// public BetBean getStakeDetails(String id)
	// {
	// PersistenceManager pm = PMF.get().getPersistenceManager();
	// try
	// {
	// Key key = KeyFactory.stringToKey(id);
	// Stake stake = pm.getObjectById(Stake.class, key);
	// return stake.toBean();
	// }
	// finally
	// {
	// pm.close();
	// }
	// }

	//
	// public UserBean getTeamOwner(String teamId) throws BackendException
	// {
	// PersistenceManager pm = PMF.get().getPersistenceManager();
	// try
	// {
	// UserGroup team = extractTeam(teamId, pm);
	//
	// for (WebetekUser player : team.getPlayers())
	// {
	// if (team.getOwnerEmail().equals(player.getEmail()))
	// {
	// return player.toBean();
	// }
	// }
	// return null;
	// }
	// finally
	// {
	// pm.close();
	// }
	// }
	//
	// private void createUserStatisticsTask(String id)
	// {
	// Queue queue = QueueFactory.getQueue("background-processing");
	// queue.add(TaskOptions.Builder.url("/workers/userStatistics").param("key",
	// id));
	// }
	//
	// private void createEmailSenderTask(String from, String to, String cc,
	// String subject, String content)
	// {
	// Queue queue = QueueFactory.getQueue("mail-queue");
	// queue.add(TaskOptions.Builder.url("/workers/emailSender").param("from",
	// from).param("to", to).param("cc", cc).param("subject", subject).param(
	// "content", content));
	// }
	//
	// private void createUpdateStakeTask(String id)
	// {
	// Queue queue = QueueFactory.getQueue("background-processing");
	// queue.add(TaskOptions.Builder.url("/workers/updateStakes").param("key",
	// id));
	// }

	// public ResponseStatus reinvestEarnings(String teamId) throws
	// WebetekLoginException, BackendException
	// {
	// PersistenceManager pm = PMF.get().getPersistenceManager();
	//
	// checkLogin();
	//
	// try
	// {
	// UserGroup team = extractTeam(teamId, pm);
	//
	// WebetekUser user = utils.getUser(pm, userService, team);
	//
	// // change stakes status...
	// double am = 0.0;
	// List<Stake> stakes = user.getStakes();
	// for (Stake stake : stakes)
	// {
	// if (stake.getStatus() == EnumStakeStatus.CLOSED)
	// {
	// // am += stake.get
	// stake.setStatus(EnumStakeStatus.ENDED);
	// }
	// }
	// return new ResponseStatus(true);
	// }
	// finally
	// {
	// pm.close();
	// }
	// }
	//
	// public PaymentBean acceptEarnings(String teamId) throws BackendException,
	// WebetekLoginException
	// {
	//
	// checkLogin();
	//
	// PersistenceManager pm = PMF.get().getPersistenceManager();
	// Transaction tx = pm.currentTransaction();
	// try
	// {
	//
	// UserGroup team = extractTeam(teamId, pm);
	//
	// WebetekUser player = utils.getUser(pm, userService, team);
	//
	// tx.begin();
	// List<Stake> stakes = player.getStakes();
	// for (Stake stake : stakes)
	// {
	// if (stake.getStatus() == EnumStakeStatus.CLOSED)
	// {
	// Double earnings = stake.getEarnings();
	// addPayment(player.getSid(), teamId, earnings, EPaymentType.EARNINGS);
	//
	// // stake.setEarnings(0.0);
	// stake.setStatus(EnumStakeStatus.ENDED);
	// }
	// }
	//
	// pm.makePersistent(player);
	// tx.commit();
	// return null;
	// }
	// finally
	// {
	// if (tx.isActive())
	// {
	// tx.rollback();
	// }
	//
	// pm.close();
	// }
	// }

	public DataStoreAPI getDbAPI()
	{
		return dbAPI;
	}

	@Override
	public void init() throws ServletException
	{
		// TODO Auto-generated method stub
		super.init();
	}
}
